﻿////////////////////////////////////////////////////////////////////
// © Copyright 2007 NeoGeo New Media GmbH (http://www.neogeo.com) //
////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////
// double click emulating variables***************************
// (helper for emulating a mouse-left-double-click)
///////////////////////////////////////////////////////////////
var firstClick = false;
var secondClick = false;
var DoubleClickX, DoubleClickY = -1;
var DoubleClickZoomEnd = -1;

///////////////////////////////////////////////////////////////
// doubleclick timer ******************************************
// (while callback a second click is handled as doubleclick)
///////////////////////////////////////////////////////////////
function TimerDoubleClick()
{    
    setTimeout("CheckDoubleClick()",300);
}

///////////////////////////////////////////////////////////////
// doubleclick timer callback *********************************
// (checks if a second click appeared while the timer is active)
///////////////////////////////////////////////////////////////
function CheckDoubleClick()
{    
    // only if within the timer-event the left-mouse has been clicked twice
    if(firstClick && secondClick)
    {
        // an emulated double-click was detected, execute double-click action
        DoubleClickZoomStart();
    }
    
    // reset the clicked mouse-button 
    firstClick = false;
    secondClick = false;
}

///////////////////////////////////////////////////////////////
// mouseposition directive ************************************
// (simple function for retriving the current mouse position relative to the window)
///////////////////////////////////////////////////////////////
var MousePosX, MousePosY = -1;
function mousePosition() 
{		
	var e = window.event;
	if(e != null)
	{	// for most browsers    	    
	    if (e.pageX || e.pageY) 	
	    {
		    MousePosX = e.pageX;
		    MousePosY = e.pageY;
	    } //for older browsers
	    else if (e.clientX || e.clientY) 	
	    {
		    MousePosX = e.clientX + document.body.scrollLeft
			    + document.documentElement.scrollLeft;
		    MousePosY = e.clientY + document.body.scrollTop
			    + document.documentElement.scrollTop;
	    }
	}
}

///////////////////////////////////////////////////////////////
// mousedown event ********************************************
// (handles the mousedown-event for the rootelement of the xaml)
///////////////////////////////////////////////////////////////
var MouseDownX, MouseDownY = -1;
function sceneMouseDown(sender, eventArgs) 
{
    //ClearAndReset(false,true);
    CalculateEdges(); // call to the global logic function
    // only continue if the mouse is within the main- or overview-canvas while the event occured
    if(eventArgs.getPosition(null).X >= LeftSpacing && eventArgs.getPosition(null).X <= (LeftSpacing + OrigSizeX) && eventArgs.getPosition(null).Y >= TopSpacing && eventArgs.getPosition(null).Y <= (TopSpacing + OrigSizeY)||(eventArgs.getPosition(null).X >= OverviewPortX && eventArgs.getPosition(null).X <= (OverviewPortX + OverviewPortSizeX) && eventArgs.getPosition(null).Y >= OverviewPortY && eventArgs.getPosition(null).Y <= (OverviewPortY + OverviewPortSizeY)))
    {
        // set the global mousedown coordinates for mouse-move behaviour
        MouseDownX = eventArgs.getPosition(null).X;
        MouseDownY = eventArgs.getPosition(null).Y;
        
        // only handle a click if the mouse-cursor is not over one of the toolbar-buttons
        var ToolbarButton = MainRootElement.findName("Help");
        if(MouseDownX < ToolbarButton["Canvas.Left"] || (MouseDownX > ToolbarButton["Canvas.Left"] && MouseDownY > ToolbarButton["Canvas.Top"]))
        {
            // if a firstclick already appeared, step into double click handling
            if(firstClick == true) 
            {
                // if the zoom level is low set the zoom-center to the mouse-cursor
                if(Zoom() <= 1.3)
                {
                    DoubleClickX =  SizeX / (OrigSizeX/MouseDownX) / Zoom();
                    DoubleClickY = SizeY / (OrigSizeY/MouseDownY) / Zoom();
                }
                else // if the zoom level is higher continue zooming into the current spot
                {
                    DoubleClickX = CenterX;
                    DoubleClickY = CenterY;
                }
                
                // if the zoom level is not at its maximum execute a chunkzoom when the mouse is doubleclicked
                if(Zoom() + 2.5 < MaxDepth * ZoomLevel + 2*ZoomLoad) 
                {
                    DoubleClickZoomEnd = Zoom() + 2.5;
                }
                else // if the zoom level is almost at its maximum execute a chunkzoom to the limit of the maxzoom
                {
                    DoubleClickZoomEnd = MaxDepth * ZoomLevel + 2 * ZoomLoad;
                }
                
                // set the mousehelper for doubleclick to true, so the event will be fired
                secondClick = true;
            }
            else // this is the first mouseclick that appeared within the timer-event
            {
                // set the mousehelper for the first click to true, so the next click within the timer-event will be the doubleclick
                firstClick = true;
            }
            // call the timerevent for the double-clicks
            TimerDoubleClick();
        }
    }
}

///////////////////////////////////////////////////////////////
// mousemove event ********************************************
// (handles the mousemove-event for the rootelement of the xaml)
///////////////////////////////////////////////////////////////
function sceneMouseMove(sender, eventArgs) 
{
    CalculateEdges(); // call to the global logic function
    navigateCancel = true; // cancel the sidebar-navigation if the mouse moves
    
    // only continue if the mouse is within the overview-canvas while the event occured
    if(eventArgs.getPosition(null).X >= OverviewPortX && eventArgs.getPosition(null).X <= (OverviewPortX + OverviewPortSizeX) && eventArgs.getPosition(null).Y >= OverviewPortY && eventArgs.getPosition(null).Y <= (OverviewPortY + OverviewPortSizeY))
    {
        // the mousemove is only possible when the zoomlevel is higher and the mousedown event occured before
        if (MouseDownX != -1 && MouseDownY != -1 && Zoom() > 1.0) 
        {   
            var sceneScale = sender.findName("sceneScale");
            var Selection = sender.findName("Selection");
            
            // set the cursor to the move-style
            Selection["Cursor"] = "Stylus";
            
            // the mousemove is only possible if the image is within the specified ranges
            if(ImgX < 0 && ImgX + SizeX > OrigSizeX && ImgY < 0 && ImgY + SizeY > OrigSizeY)
            {
                // function for translating the mousemove behaviour to a mousedrag behaviour
                var transX = (eventArgs.getPosition(null).X-MouseDownX) * (4 + 4/Zoom());
                var transY = (eventArgs.getPosition(null).Y-MouseDownY) * (4 + 4/Zoom());
                if(ImgX - transX < 0 && ImgX + SizeX > OrigSizeX + transX )
                    sceneScale.CenterX += transX;
                if(ImgY - (transY-10) < 0 && ImgY + SizeY - transY - 5 > OrigSizeY)
                    sceneScale.CenterY += transY;
                MouseDownX = eventArgs.getPosition(null).X;
                MouseDownY = eventArgs.getPosition(null).Y;  
                // when moving the mouse in drag mode cancel any other zoom or navigate event
                ZoomStop();
                           
            }
            else // if the image went out of these ranges reset the image to the maximum range
            {                
                if(ImgX >= 0) sceneScale.CenterX = LeftSpacing + 1;
                if(ImgX + SizeX <= OrigSizeX) sceneScale.CenterX = LeftSpacing + OrigSizeX - 5;
                if(ImgY >= 0) sceneScale.CenterY = TopSpacing + 1;
                if(ImgY + SizeY <= OrigSizeY) sceneScale.CenterY = TopSpacing + OrigSizeY - 5;                
            }
            // according to the movement, refresh the overview-selection to match the position of the image
            OverviewPan();
        }
    }
    else if(eventArgs.getPosition(null).X > LeftSpacing && eventArgs.getPosition(null).X < (LeftSpacing + OrigSizeX) && eventArgs.getPosition(null).Y > TopSpacing && eventArgs.getPosition(null).Y < (TopSpacing + OrigSizeY))
    { // only continue if the mouse is within the main-canvas while the event occured
        // the mousemove is only possible when the zoomlevel is higher and the mousedown event occured before
        if (MouseDownX != -1 && MouseDownY != -1 && Zoom() > 1.0) 
        {   
            var sceneScale = sender.findName("sceneScale");
            var ZoomCanvas = sender.findName("ZoomCanvas");
            var sceneTranslate = sender.findName("sceneTranslate");
            
            // set the cursor to the move-style
            ZoomCanvas["Cursor"] = "Stylus";
            
            // the mousemove is only possible if the image is within the specified ranges
            if(ImgX < 0 && ImgX + SizeX > OrigSizeX && ImgY < 0 && ImgY + SizeY > OrigSizeY)
            {
                // function for translating the mousemove behaviour to a mousedrag behaviour
                var transX = (MouseDownX - eventArgs.getPosition(null).X) / Zoom();
                var transY = (MouseDownY - eventArgs.getPosition(null).Y) / Zoom();
                if(ImgX - transX < 0 && ImgX + SizeX > OrigSizeX + transX )
                    sceneScale.CenterX += transX;
                if(ImgY - (transY-5) < 0 && ImgY + SizeY - transY > OrigSizeY)
                    sceneScale.CenterY += transY;
                MouseDownX = eventArgs.getPosition(null).X;
                MouseDownY = eventArgs.getPosition(null).Y;   
                // when moving the mouse in drag mode cancel any other zoom or navigate event
                ZoomStop();               
            }
            else // if the image went out of these ranges reset the image to the maximum range            
            {    
                if(ImgX >= 0) sceneScale.CenterX = LeftSpacing+2;
                if(ImgX + SizeX <= OrigSizeX) sceneScale.CenterX = LeftSpacing + OrigSizeX - 2;
                if(ImgY >= 0) sceneScale.CenterY = TopSpacing+1;
                if(ImgY + SizeY <= OrigSizeY) sceneScale.CenterY = TopSpacing + OrigSizeY - 2;
            }
            // according to the movement, refresh the overview-selection to match the position of the image
            OverviewPan();
        }
    }
    else // if the mouse is not focused on either of the canvas, cancel the mousemove by calling the mouseup event
    {
        sceneMouseUp(sender,eventArgs);
    }  
}

///////////////////////////////////////////////////////////////
// mouseup event *********************************************
// (handles the mouseup-event for the rootelement of the xaml)
///////////////////////////////////////////////////////////////
function sceneMouseUp(sender, eventArgs) 
{
    // reset the cursors of both canvas' with the original one
    var ZoomCanvas = MainRootElement.findName("ZoomCanvas");
    var Selection = MainRootElement.findName("Selection");
    Selection["Cursor"] = "Hand";
    ZoomCanvas["Cursor"] = "Hand";
    
    // reset the global mouseclick coordinates
    MouseDownX = -1;
    MouseDownY = -1;
    
    // when the mouseleftbutton is finally released the tile logic can finally be processed
    processTileLogic();
}

///////////////////////////////////////////////////////////////
// mousewheel delegates ***************************************
// (for handling the mousewheel event)
///////////////////////////////////////////////////////////////
WheelHelper.prototype.wheelScrolled = null;
WheelHelper.prototype.delegate = null;

///////////////////////////////////////////////////////////////
// mousewheel helper function**********************************
// (handles the mouseup-event for the rootelement of the xaml)
///////////////////////////////////////////////////////////////
function WheelHelper() {
    // creates the delegate handler for the mousewheel event
    this.delegate = Silverlight.createDelegate(this, this.handleMouseWheel);
    if (window.addEventListener) {
        // DOMMouseScroll is for mozilla.
        window.addEventListener('DOMMouseScroll', this.delegate, false);
    }
    window.onmousewheel = document.onmousewheel = this.delegate;
}

///////////////////////////////////////////////////////////////
// mousewheel event *******************************************
// (eventhandler for the mousewheel event in the browser)
///////////////////////////////////////////////////////////////
WheelHelper.prototype.handleMouseWheel = function(event) {
    var delta = 0;
    if (!event) // for ie
        event = window.event;
        
    if (event.wheelDelta) { // for ie and opera
        delta = event.wheelDelta/120;
        // in opera 9, delta differs in sign as compared toie
        if (window.opera)
        {
            delta = -delta;
        }
            
    }
    else if (event.detail) { // mozilla case
        // in mozilla, sign of delta is different than inie
        // also delta is multiple of 3
        delta = -event.detail/3;
        // sign is only reversed in windows ff
        if(navigator.userAgent.indexOf("Macintosh") != -1)
            delta=-delta;
    }

    // if delta is nonzero, handle it
    if (delta && this.wheelScrolled)
        this.wheelScrolled(delta);
        
    // prevent default actions caused by mouse wheel
    if (event.preventDefault)
        event.preventDefault();
    
    event.returnValue = false;
}

///////////////////////////////////////////////////////////////
// mousewheel detach function *********************************
// (detaches from the subscribed mousewheel event)
///////////////////////////////////////////////////////////////
WheelHelper.prototype.detach = function() {
    if (this.delegate != null) {
        if (window.removeEventListener) {
            window.removeEventListener('DOMMouseScroll', this.delegate, false);
        }
        
        // ie and opera
        window.onmousewheel = document.onmousewheel = null;
        
        this.delegate = null;
    }
}

///////////////////////////////////////////////////////////////
// executing mousewheel directive *****************************
// (function for handling the occuring mousewheel event)
///////////////////////////////////////////////////////////////
function handleMouseWheel(delta) 
{
    // delta: 1 for mousewheel up in, -1 for mousewheel down
    
    // get the current mouseposition
    mousePosition();
    // only react if the maincanvas or overviewcanvas has mousefocus
    if(MousePosX >= OverviewLeftSpacing && MousePosX <= (OverviewLeftSpacing + OverviewSizeX) && MousePosY >= OverviewTopSpacing && MousePosY <= (OverviewTopSpacing + OverviewSizeY))
    {    
        // mousefocus is on overviewcanvas
        if (delta < 0) ZoomOut();
        else TargetZoomIn(true); // true because the mousewheel shall respond to the overview canvas
    }
    else if(MousePosX >= LeftSpacing && MousePosX <= (LeftSpacing + OrigSizeX) && MousePosY >= TopSpacing && MousePosY <= (TopSpacing + OrigSizeY))
    {    
        // mousefocus is on maincanvas
        if (delta < 0) ZoomOut();
        else TargetZoomIn(); // false/nothing because the mousewheel shall respond to the main canvas
    }
}